/*
 * intnumberobject.cpp
 *
 *  Created on: Oct 30, 2009
 *      Author: Silviu Caragea
 */

#include "includes/arrayobject.h"

namespace templatipus {
//constructor && destructor


TArrayObject::TArrayObject() :
	TemplateObject() {

}

TArrayObject::TArrayObject(const TemplateObject &other) :
	TemplateObject(other) {
	this->internalArray.clear();
	if (other.getType() == this->getType()) {
		TArrayObject * otherObj = (TArrayObject*) &other;
		this->internalArray = otherObj->internalArray;
	} else {
		this->add(other);
	}
}

TArrayObject::TArrayObject(const int8 &rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const int16 &rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const int32 &rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const int64 &rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const float32 &rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const float64 &rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const utf8Ptr rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const unicodePtr rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const std::wstring& rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::TArrayObject(const std::string& rhs) :
	TemplateObject(rhs) {
	this->internalArray.clear();
	this->add(rhs);
}

TArrayObject::~TArrayObject() {

}

TObjectType TArrayObject::getType() const {
	return ARRAY_TYPE;
}

TIntNumberObject TArrayObject::getLength() const {
	return TIntNumberObject((int64) internalArray.size());
}

void TArrayObject::add(const TemplateObject & object) {
	yasper::ptr<TemplateObject> newPtr = object.newInstance();
	*newPtr = object;

	this->internalArray.push_back(newPtr);
}

void TArrayObject::remove(const uint64 & index) {
	this->internalArray.erase(internalArray.begin() + index);
}

const TemplateObject& TArrayObject::operator [](const uint64 index) {
	return *this->internalArray[index];
}

const TemplateObject& TArrayObject::operator [](const std::string &key) {
	if (key .compare("length") == 0) {
		return this->getLength();
	}

	return *this;
}

const TemplateObject& TArrayObject::operator [](const std::wstring &key) {
	if (key.compare(L"length") == 0)
	{
		return this->getLength();
	}

	return *this;
}

const TemplateObject& TArrayObject::operator ()(const std::wstring &key,const TemplateObject &params)
{
	if (key.compare(L"add") == 0)
	{
		this->add(params);
	}
	else if (key.compare(L"remove") == 0)
	{
		this->remove(params);
	}

	return *this;
}

const TemplateObject& TArrayObject::operator ()(const std::string &key,const TemplateObject &params)
{
	if (key.compare("add") == 0)
	{
		this->add(params);
	}
	else if (key.compare("remove") == 0)
	{
		this->remove(params);
	}

	return *this;
}

const TemplateObject& TArrayObject::operator +=(const TemplateObject &other)
{
	if (other.getType() == this->getType())
	{
		TArrayObject * otherObj = (TArrayObject*) &other;
		std::copy( otherObj->internalArray.begin(), otherObj->internalArray.end(), std::back_inserter( this->internalArray ) );
	}
	else
	{
		this->add(other);
	}

	return *this;
}

TArrayObject TArrayObject::operator +(const TArrayObject &other)
{
	TArrayObject obj(this);
	obj+=other;
	return obj;
}

tbool TArrayObject::operator ==(const TemplateObject &other) const
{
	if(other.getType() != ARRAY_TYPE)
	{
		return false;
	}

	TArrayObject* temp = (TArrayObject*)&other;
	return temp->internalArray == this->internalArray;
}

tbool TArrayObject::operator !=(const TemplateObject &other) const
{
	return !(*this == other);
}

//assigning values
	TemplateObject& TArrayObject::operator=(const TemplateObject &other)
	{
		this->internalArray.clear();
		if (other.getType() == this->getType())
		{
			TArrayObject * otherObj = (TArrayObject*) &other;
			this->internalArray = otherObj->internalArray;
		}
		else
		{
			this->add(other);
		}

		return *this;
	}

	TemplateObject& TArrayObject::operator=(const int8 &other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const int16 &other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const int32 &other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const int64 &other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const float32 &other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const float64 &other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const std::wstring& other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const std::string& other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const utf8Ptr other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	TemplateObject& TArrayObject::operator=(const unicodePtr other)
	{
		this->internalArray.clear();
		this->add(other);
		return *this;
	}

	//comparison

	//String stuff
	TArrayObject::operator std::string() const
	{
		std::string buffer;
		uint64 array_size = this->internalArray.size();

		if(array_size)
		{
			buffer+="[";

			 for(uint64 i = 0; i< array_size;i++)
			 {
				 TemplateObject *obj = (TemplateObject*)this->internalArray.at(i);

				 buffer+="\"";
				 buffer+=(std::string)*obj;
				 buffer+="\"";

				 if(i != array_size-1)
					 buffer+=",";
			 }

			 buffer+="]";
		}

		return buffer;

	}

	TArrayObject::operator std::wstring() const
	{
		std::wstring buffer;
		uint64 array_size = this->internalArray.size();

		if(array_size)
		{
			buffer+=L"[";

			 for(uint64 i = 0; i< array_size;i++)
			 {
				 TemplateObject *obj = (TemplateObject*)this->internalArray.at(i);

				 buffer+=L"\"";
				 buffer+=(std::wstring)*obj;
				 buffer+=L"\"";

				 if(i != array_size-1)
					 buffer+=L",";
			 }

			 buffer+=L"]";
		}

		return buffer;

	}

	//Conversion operators

	TArrayObject::operator tbool() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator int8() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator uint8() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator int16() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator uint16() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator int32() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator uint32() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator int64() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator uint64() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator float32() const
	{
		return this->internalArray.size();
	}

	TArrayObject::operator float64() const
	{
		return this->internalArray.size();
	}

}
